/*
 * Titulo: OrdenamientosExternos.java
 * Autor: Oswaldo Ceballos Zavala ( Inu )
 * Descripcion: Clase para el ordenamiento del archivo nacional con mezcla
 * equilibrada.
 *
 * Universidad Autonoma de Yucatan
 *
 */

package util;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;


import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;
import modelo.Escuela;

/**
 *
 * @author Oswaldo Ceballos Zavala
 */
public class OrdenamientosExternos {
     
    
    
    private static ArrayList<Escuela> escuelas;
    
    public static ArrayList<Escuela> getEscuelas(){
        return escuelas;
    }
    
    /**
     * Crea el archivo con la permutacion identidad y crea la referencia a
     * la lista original de escuelas no ordenadas.
     * 
     * @param nacionales Un ArrayList de elementos escuela
     * @throws IOException No se puede escribir en el archivo correctamente
     */
    public static void preparaArchivoNacional( ArrayList<Escuela> nacionales ) throws IOException{
        
        escuelas = nacionales;
        escuelas.add(  new Escuela(null, null, null, -1.0 )  );
        
        PrintWriter fileOut = new PrintWriter ( new FileWriter ("F.txt") );
           for (int i = 0; i < 89531; i++){
               fileOut.println(i);
               fileOut.flush();
           }
    
    }
    
    
    
    /**
     *Intercambia el valor de una variable boolean
     * 
     * @param b Un valor booleano
     * @return true si b es false, devuelve false en caso contrario
     */
    public static boolean cambiob(boolean b){
        return !b;
    }
   
    
    /**
     * 
     * Algoritmo de ordenamiento externo mezcla equilibrada
     * 
     * @param F El archivo a ordenar
     * @param F1 Archivo auxiliar
     * @param F2 Archivo auxiliar
     * @param F3 Archivo auxiliar
     * @return Un ArrayList de Escuela ordenado con los valores del archivo nacional 
     * @throws IOException No se puede leer el archivo correctamente
     */
    public static ArrayList<Escuela> mezclaequilibrada(String F, String F1,String F2, String F3)throws IOException {
       
        particioninicial(F,F2,F3);
       
        String inLineF1 = "";
        String inLineF3 = "";
       
        boolean BAND = true;
        do {
           
            if (BAND == true){
                particionfusion(F2,F3,F,F1);
                BAND = false;
            }
            else{
                particionfusion(F,F1,F2,F3);
                BAND = true;
            }
       
        FileReader fr1 = new FileReader(F1);
        BufferedReader br1 = new BufferedReader(fr1);
        FileReader fr3 = new FileReader(F3);
        BufferedReader br3 = new BufferedReader(fr3);
       
        inLineF1 = br1.readLine();
        inLineF3 = br3.readLine();
       
        br1.close();
        br3.close();
        }
        while(inLineF1 != null || inLineF3 !=null);
        
        //reconstruir
        Scanner fileIn = new Scanner ( new FileReader ("F.txt") );
        ArrayList<Escuela> ordenado = new ArrayList();
        
        int index;
        while ( fileIn .hasNext()){
            index = fileIn.nextInt();
            
            ordenado.add( escuelas.get(index) );    
            
            
        } //fin while reconstruir
        
        return ordenado;
        
    }
   
   
    /**
     *
     * Particiona el archivo objetivo para iniciar la mezcla equilibrada
     * 
     * @param F El archivo a ordenar
     * @param F2 Archivo auxiliar
     * @param F3 Archivo auxiliar
     * @throws IOException No se puede eleer o escribir en el archivo correctamente
     */
    public static void particioninicial(String F,String F2, String F3) throws IOException {
       
        int Aux = 89531, R = 89531 ;
        boolean BAND= true;
       
       
        FileReader fr = new FileReader(F);
        BufferedReader br = new BufferedReader(fr);
       
        FileWriter fw2 = new FileWriter(F2);
        BufferedWriter bw2 = new BufferedWriter(fw2);
        PrintWriter pw2 = new PrintWriter(bw2);
       
        FileWriter fw3 = new FileWriter(F3);
        BufferedWriter bw3 = new BufferedWriter(fw3);
        PrintWriter pw3 = new PrintWriter(bw3);
       
        String inLineF = br.readLine();
       
        if(inLineF!=null){
          
        pw2.println(inLineF);
        BAND = true;
        Aux = Integer.parseInt(inLineF);
        }
       
        while (inLineF != null){
           
            inLineF = br.readLine();
            if(inLineF!=null){
                R =Integer.parseInt(inLineF);
            if ( escuelas.get(R).getPromedioGeneral() >= escuelas.get(Aux).getPromedioGeneral() ){
                //if( R>= Aux){
                Aux = Integer.parseInt(inLineF);
                if(BAND == true){
                    
                    pw2.println(inLineF);
                }
                else{
                    
                    pw3.println(inLineF);
                }
            }
            else{
                Aux = Integer.parseInt(inLineF);
                if(BAND == true){
                    
                    pw3.println(inLineF);
                    BAND = false;
                }
                else{
                    
                    pw2.println(inLineF);
                    BAND = true;
                }
            }
        }
       
        pw2.flush();
        pw3.flush();
       
       
        } //fin while
        pw2.close();
        pw3.close();
        br.close();
    }
   
   
    /**
     * 
     * Particion-fusion del algoritmo de mezcla equilibrada
     * 
     * @param FA Archivo de entrada
     * @param FB Archivo de entrada
     * @param FC Archivo de salida
     * @param FD Archivo de salida
     * @throws IOException No se puede leer o escribir en el archivo correctamente
     */
    public static void particionfusion(String FA, String FB, String FC, String FD) throws IOException{
       
        int R1 = 89531, R2 = 89531, Aux =89531;
        boolean B,DELE1, DELE2;
       
        FileReader frFA = new FileReader(FA);
        BufferedReader brFA = new BufferedReader(frFA);
       
        FileReader frFB = new FileReader(FB);
        BufferedReader brFB = new BufferedReader(frFB);
       
       
        FileWriter fwFC = new FileWriter(FC);
        BufferedWriter bwFC = new BufferedWriter(fwFC);
        PrintWriter pwFC = new PrintWriter(bwFC);
       
        FileWriter fwFD = new FileWriter(FD);
        BufferedWriter bwFD = new BufferedWriter(fwFD);
        PrintWriter pwFD = new PrintWriter(bwFD);
       
        B = true;
        String inLineFA = brFA.readLine();
        String inLineFB = brFB.readLine();
       
       
       
        if(inLineFA!=null){
           R1 = Integer.parseInt(inLineFA);
        }
        if(inLineFB!=null){
           R2 = Integer.parseInt(inLineFB);
        }
        if (escuelas.get(R1).getPromedioGeneral() < escuelas.get(R2).getPromedioGeneral()){
        //if(R1<R2){
            Aux = R1;
        }
        else{
            Aux = R2;
        }
       
        DELE1 = false;
        DELE2 = false;
       
        while((inLineFA!=null||DELE1!=true)&&(inLineFB!=null||DELE2!=true)){
           
            
            pwFC.flush();
            pwFD.flush();
           
            if(DELE1==true){
                inLineFA = brFA.readLine();
                DELE1 = false;
       
            }
            if(DELE2 == true){
                inLineFB = brFB.readLine();
                DELE2 = false;
                
            }
            if(inLineFA!=null){
                R1 = Integer.parseInt(inLineFA);
            }
            else{
                R1=89531;
            }
            if(inLineFB!=null){
                R2 = Integer.parseInt(inLineFB);
            }
            else{
                R2=89531;
            }
           
           
            if ( escuelas.get(R1).getPromedioGeneral() < escuelas.get(R2).getPromedioGeneral() ) {
            //if(R1<R2){
                if ( escuelas.get(R1).getPromedioGeneral()  >= escuelas.get(Aux).getPromedioGeneral() ){
                //if( R1>=Aux ){
                    Aux = ayuda1(Aux,R1,FC,FD,B);
                    DELE1 = true;
                }
                else{
                    if ( escuelas.get(R2).getPromedioGeneral() >= escuelas.get(Aux).getPromedioGeneral() ){
                    //if(R2>= Aux){
                        Aux = ayuda1(Aux,R2,FC,FD,B);
                        DELE2 = true;
                    }
                    else{
                        Aux = ayuda2(Aux,R1,FC,FD,B);
                        B = cambiob(B);
                        DELE1 = true;
                    }
                }
            }
            else{
                if ( escuelas.get(R2).getPromedioGeneral() >= escuelas.get(Aux).getPromedioGeneral() ){
                //if(R2>=Aux){
                    Aux = ayuda1(Aux,R2,FC,FD,B);
                    DELE2 = true;
                }
                else{
                    if ( escuelas.get(R1).getPromedioGeneral() >= escuelas.get(Aux).getPromedioGeneral() ){
                    //if(R1>=Aux){
                       Aux = ayuda1(Aux,R1,FC,FD,B);
                        DELE1 = true;
                    }
                    else{
                       Aux = ayuda2(Aux,R2,FC,FD,B);
                       B = cambiob(B);
                        DELE2 = true;
                    }
                }
            }
             
             
        } //fin while
       
        
        if(DELE1 == true && inLineFA == null){
            if(inLineFB!=null){
            ayuda3(Aux,R2,FB,FC,FD,B);}
        }
        if(DELE2 == true && inLineFB == null){
            if(inLineFA!=null){
                ayuda3(Aux,R1,FA,FC,FD,B);
            }
        }
       
        pwFC.close();
        pwFD.close();
    }
   
   
    /**
     *
     * Metodo auxiliar de particionFusion
     * 
     * @param Aux
     * @param R
     * @param FC
     * @param FD
     * @param B
     * @return
     * @throws IOException No se puede leer o escribir en el archivo correctamente
     */
    public static int ayuda1(int Aux, int R, String FC, String FD, boolean B) throws IOException {
        Aux = R;
       
        FileWriter fwFC = new FileWriter(FC,true);
        BufferedWriter bwFC = new BufferedWriter(fwFC);
        PrintWriter pwFC = new PrintWriter(bwFC);
       
        FileWriter fwFD = new FileWriter(FD,true);
        BufferedWriter bwFD = new BufferedWriter(fwFD);
        PrintWriter pwFD = new PrintWriter(bwFD);
        if (B){
            if(R != 89531){
         
            pwFC.println(R);
            }
            pwFC.close();
         
        }
        else{
            if(R!=89531){
         
            pwFD.println(R);
            }
            pwFD.close();
         
        }
        
        return Aux;
       
    }
   
    /**
     *
     * Metodo auxiliar del metodo particionFusion
     * 
     * @param Aux
     * @param R
     * @param FC
     * @param FD
     * @param B
     * @return
     * @throws IOException
     */
    public static int ayuda2(int Aux, int R, String FC, String FD, boolean B) throws IOException{
        FileWriter fwFC = new FileWriter(FC,true);
        BufferedWriter bwFC = new BufferedWriter(fwFC);
        PrintWriter pwFC = new PrintWriter(bwFC);
       
        FileWriter fwFD = new FileWriter(FD,true);
        BufferedWriter bwFD = new BufferedWriter(fwFD);
        PrintWriter pwFD = new PrintWriter(bwFD);
        Aux = R;
        if(B){
            if(R!=89531){
            
            pwFD.println(R);
            }
            pwFD.close();
            
            B= false;
        }
        else{
            if(R!=89531){
            
            pwFC.println(R);
            }
            pwFC.close();
            
            B = true;
        }
        
        return Aux;
    }
   
   
    /**
     *
     * Metodo auxiliar del metodo particionFusion
     * 
     * @param Aux
     * @param R
     * @param F
     * @param FC
     * @param FD
     * @param B
     * @throws IOException
     */
    public static void ayuda3(int Aux,int R, String F, String FC, String FD, boolean B) throws IOException {
       
       
        FileReader frF = new FileReader(F);
        BufferedReader brF = new BufferedReader(frF);
        String inLine =  String.valueOf(R),inLineF="dsa";
       
        if ( escuelas.get(R).getPromedioGeneral() >= escuelas.get(Aux).getPromedioGeneral()){
        //if( R>=Aux ){
            Aux = ayuda1(Aux,R,FC,FD,B);
        }
        else{
            Aux = ayuda2(Aux,R,FC,FD,B);
            B = cambiob(B);
        }
       
        while(inLineF.compareToIgnoreCase(inLine)!=0){
            inLineF= brF.readLine();
        }
       
       
        while(inLineF!=null){
           
            inLineF = brF.readLine();
            if(inLineF != null){
                R = Integer.parseInt(inLineF);
                if (escuelas.get(R).getPromedioGeneral() >= escuelas.get(Aux).getPromedioGeneral()){
                //if(R>=Aux){
                    Aux = ayuda1(Aux,R,FC,FD,B);
                }
                else{
                    Aux = ayuda2(Aux,R,FC,FD,B);
                    B = cambiob(B);
                }
            }    
        }
    }
   
     
   
    /*********************************************
     *
     *  PRUEBAS
     *
     *********************************************/
   
    public static void main(String args[]){
       
       String F = "F.txt",F1="F1.txt",F2="F2.txt",F3="F3.txt";
       
       try{
         
         mezclaequilibrada(F,F1,F2,F3);
         
         
       }catch(IOException e){}
       
    }


} //fin clase OrdenamientosExternos

